package com.qy.util;



import java.util.Map;
import java.util.Random;

/**
 * 
 * 概率常用函数
 * 
 * @author zhangwl
 *
 * @date   2014年11月15日
 */
public class ProbabilityUtil {
	
	
	/**
	 * 
	 * 根据概率数组计算总和，然后随机生成一个0到概率总和的随机数，
	 * 并返回随机数在概率数组的区间位置，区间位置以0开始
	 * 概率数组必须没有被统计，这里会自动统计，并不修改原始数据
	 * @param probabilities
	 * 		概率数组
	 * @return
	 */
	public static int generateZoneByProbabilities(int[] probabilities){
		int[] clonedProbabilities = probabilities.clone();
		int sumProbability = sum(clonedProbabilities);
		for(int i=0,length=clonedProbabilities.length-1;i<length;i++){
			int j = i+1;
			//统计数组前面的概率加入到后一个概率中
			clonedProbabilities[j] = clonedProbabilities[j] + clonedProbabilities[i];
		}
		return generateZoneByProbabilities(sumProbability, clonedProbabilities);
	}
	
	/**
	 * 根据概率总和随机生成一个0到概率总和的随机数，
	 * 并返回随机数在概率数组的区间位置，区间位置以0开始
	 * 概率数组必须已经被统计
	 * @param probabilities
	 * 		概率数组
	 * @return
	 */
	public static int generateZoneByProbabilities(int sumProbability, int[] probabilities){
		int randomNumber = randomInt(sumProbability);
		int result = calculateZone(randomNumber, probabilities);
		return result;
	}
	/**
	 * 计算一个数值在数组的区间位置，数组必须是按升序排序的
	 * 
	 * @param calculateValue 要计算的数值
	 * 			
	 * @param valueArray  数值数组
	 * 
	 * @return 找不到区间返回-1
	 */
	public static int calculateZone(int calculateValue, int[] valueArray){
		int result = -1;
		for(int i=0,length=valueArray.length; i<length;i++){
			if(calculateValue <= valueArray[i]){
				result = i;
				break;
			}
		}
		return result;
	}
	/**
	 * 求和
	 * @param probabilities
	 * 		概率数组
	 * @return
	 */
	public static int sum(int[] probabilities){
		int sum = 0;
		for(int i : probabilities){
			sum += i;
		}
		return sum;
	}
	/**
	 * 根据概率随即生成一个在0-probability区间的值，不包含0
	 * @param probability
	 * 		概率和，必须大于0
	 * @return
	 */
	public static int randomInt(int probability){
		int randomNumber = (int) Math.round((1+Math.random()*(probability-1)));
		return randomNumber;
	}
	
	/**
	 * 从map的集合中随机出key
	 * @param map value为概率
	 * @return
	 */
	public static int getRandomValue(Map<Integer, Integer> map) {
		int base = 0;
		for(int key : map.keySet()) {
			base += map.get(key);
		}
		int randomV = new Random().nextInt(base);
		int increament = 0;
		for(int key : map.keySet()) {
			int v = map.get(key);
			if(increament <= randomV && increament + v > randomV) {
				return key;
			} else {
				increament += v;
			}
		}
		return 0;
	}
	
	/**
	 * 从map的集合中随机出key
	 * @param map value为概率
	 * @return
	 */
	public static String getMapRandomValue(Map<String, Integer> map) {
		int base = 0;
		for(String key : map.keySet()) {
			base += map.get(key);
		}
		int randomV = new Random().nextInt(base);
		int increament = 0;
		for(String key : map.keySet()) {
			int v = map.get(key);
			if(increament <= randomV && increament + v > randomV) {
				return key;
			} else {
				increament += v;
			}
		}
		return null;
	}
	
	/**
	 * 随机获取一个数组中的值
	 * @param obj 数组对象
	 * @return
	 */
	public static Object getArrayRandomValue(Object[] obj){
		int random=(int) (Math.random()*obj.length);
		return obj[random];
	}
	
	public static void main(String[] args){
		int i = randomInt(22);
		int[] valueArray = {10,22};
		int randomIndex = generateZoneByProbabilities(valueArray);
		System.out.println(i);
		System.out.println(randomIndex);
	}
}
